usage:
	@echo "--- available targets ---"
	@echo "class_index.mk     - generate class index"
	@echo "class_descriptions - generate class descriptions"
	@echo "file_overviews     - generate file overviews"
	@echo "genode.git         - download Genode source code"
	@echo "all                - generate everything"
	@echo "clean              - clean downloaded and generated files"

VERBOSE ?= @


#
# Obtaining the Genode source code, from which to extract specification
#
# Unless GENODE_DIR is set manually (e.g., via the make command line), the
# source code is downloaded from the official Genode Git repository. The
# download is triggered via the class_index.mk dependency.
#

GENODE_GIT_URL := https://github.com/genodelabs/genode.git
GENODE_GIT_REV := 64ee151d07a65dd0a77039817cb9a7fa11b53a6e
#GENODE_GIT_REV := 18.05

ifeq ($(GENODE_DIR),)
GENODE_DIR := genode.git
class_index.mk: genode.git/checked_out.tag
clean: clean_local_genode_git
endif

genode.git:
	git clone $(GENODE_GIT_URL) $@

genode.git/checked_out.tag: genode.git
	cd genode.git; git reset --hard $(GENODE_GIT_REV)
	touch $@

clean_local_genode_git:
	rm -rf genode.git


#
# Definition of the parts of the source code that contains the functional
# specification. All header files in those directories are parsed using the
# genode/tool/parse_cxx tool. For each header, a file with the suffix .token
# is created, which contains the abstract syntax tree of the corresponding
# header file.
#

#define BASE_INCLUDE_DIRS
#  util
#  base
#endef

#define OS_INCLUDE_DIRS
#  os
#  util
#endef

define BASE_INCLUDE_DIRS
  base
  cpu
  cpu_session
  cpu_thread
  dataspace
  io_mem_session
  io_port_session
  irq_session
  log_session
  parent
  pd_session
  region_map
  rm_session
  rom_session
  root
  session
  trace_session
  util
  spec/32bit
  spec/64bit
  timer_session
endef

define OS_INCLUDE_DIRS
  audio_out_session
  block_session
  file_system_session
  framebuffer_session
  gpio_session
  init
  input_session
  nic_session
  nitpicker_session
  os
  packet_stream_rx
  packet_stream_tx
  platform_session
  platform_device
  regulator_session
  report_session
  rtc_session
  spec/x86
  terminal_session
  uart_session
  usb_session
  util
endef

GENODE_ABS_DIR := $(realpath $(shell echo $(GENODE_DIR)))

API_DIRS := $(addprefix repos/base/include/,$(BASE_INCLUDE_DIRS)) \
            $(addprefix repos/os/include/,$(OS_INCLUDE_DIRS))

SRC_H := $(shell test -d $(GENODE_DIR) && (cd $(GENODE_DIR); \
             for i in $(API_DIRS); do \
                 find $$i -name "*.h"; done))

# list of token files to generate
TOKEN_FILES := $(SRC_H:.h=.h.tokens)

$(SRC_H):
	$(VERBOSE)mkdir -p $(dir $@)
	$(VERBOSE)ln -sf $(GENODE_ABS_DIR)/$@ $@

%.h.tokens: %.h
	@echo "extract tokens from $^"
	$(VERBOSE)$(GENODE_ABS_DIR)/tool/parse_cxx -format tokens $^ > $@


#
# Generate class index
#

# include class index prior generated via the rule below
ifeq ($(filter clean,$(MAKECMDGOALS)),)
-include class_index.mk
endif

class_index.mk: $(TOKEN_FILES) Makefile gen_class_index util.tcl
	$(VERBOSE)echo "# generated by ./gen_class_index" > $@
	@for i in $(TOKEN_FILES); do \
		echo "generate class index of $$i"; \
		./gen_class_index $$i >> $@ ;done


#
# All rules as invoked by the top-level Makefile of the manual
#
# We process the generating steps in a separate make instance, which will
# include the class_index.mk file as producted by the initial instance.
#

all: class_index.mk
	make class_descriptions file_overviews


#
# Generate class descriptions
#
# Each class-description snippet contains a class overview and a box for each
# method with further details.
#

CLASS_DESCRIPTIONS := $(addprefix classes/,$(addsuffix /description.tex,$(CLASSES)))

$(CLASS_DESCRIPTIONS) : Makefile gen_class_description util.tcl latex.tcl

class_descriptions: $(CLASS_DESCRIPTIONS)

classes/%/diagram.tikz:
	$(VERBOSE)mkdir -p $(dir $@)
	@echo "generate class diagram for ${CLASS_NAME($*)}"
	$(VERBOSE)./gen_class_diagram --class "${CLASS_NAME($*)}" ${CLASS_HEADER($*)}.tokens > $@

classes/%/description.tex:
	$(VERBOSE)mkdir -p $(dir $@)
	@echo "generate class description for ${CLASS_NAME($*)}"
	$(VERBOSE)./gen_class_description --class "${CLASS_NAME($*)}" ${CLASS_HEADER($*)}.tokens > $@


#
# Generate file overviews
#
# The following headers contain types and free-standing functions that are not
# covered by the class descripton above.
#

FILE_OVERVIEW_HEADERS := repos/base/include/util/string.h \
                         repos/base/include/util/construct_at.h \
                         repos/base/include/base/blocking.h \
                         repos/base/include/base/cache.h \
                         repos/base/include/base/component.h \
                         repos/base/include/base/env.h \
                         repos/base/include/base/log.h \
                         repos/base/include/base/output.h \
                         repos/base/include/base/snprintf.h \
                         repos/base/include/base/stdint.h \
                         repos/base/include/spec/64bit/base/fixed_stdint.h \
                         repos/base/include/spec/32bit/base/fixed_stdint.h \
                         repos/base/include/rom_session/rom_session.h \
                         repos/base/include/io_mem_session/io_mem_session.h \
                         repos/os/include/file_system_session/file_system_session.h

FILE_OVERVIEWS := $(addsuffix .overview.tex,$(FILE_OVERVIEW_HEADERS))

$(FILE_OVERVIEWS) : $(FILE_OVERVIEW_HEADERS)

file_overviews: $(FILE_OVERVIEWS)

%.h.overview.tex: %.h.tokens
	@echo "generate file overview for $*"
	$(VERBOSE)./gen_file_overview $< > $@


#
# Clean rules
#

clean:
	rm -rf classes
	rm -rf repos
	rm -f class_index.mk

ALL_CLASS_NAMES = $(foreach C,$(CLASSES),${CLASS_NAME($C)})

check_spec_complete: class_index.mk
	@$(foreach C,$(ALL_CLASS_NAMES),\
	    (grep "$C" ../functional_specification.txt > /dev/null || \
	     echo "missing class description for '$C'");)

